<template>
  <div ref="barChart" :class="{ 'no-data': !data.length }">
    <span v-if="!data.length">暂无数据</span>
  </div>
</template>
<script>
import * as echarts from 'echarts/lib/echarts';
import 'echarts/lib/chart/bar';
import 'echarts/lib/component/title';
import 'echarts/lib/component/grid';
import 'echarts/lib/component/tooltip';
import 'echarts/lib/component/legend';
import { getAlgorithmResult } from '@/api/general';
import mixin from './mixin';

export default {
  name: 'BarChart',
  mixins: [mixin],
  props: {
    direction: { // 柱状图方向，horizontal为水平排布（bar纵向），vertical为垂直排布（bar横行）
      type: String,
      default: () => 'horizontal',
    },
  },
  data() {
    return {
      chart: null,
      option: {},
    };
  },
  methods: {
    initChart() {
      this.chart = echarts.init(this.$refs.barChart);
      this.option = {
        grid: {
          containLabel: true,
          left: 0,
          right: 0,
          bottom: 0,
        },
        title: {
          show: this.title.length > 0,
          text: this.title,
          left: 'center',
          textStyle: {
            color: '#000',
            fontSize: 20 * this.scale,
          },
        },
        legend: {
          show: this.showLegend,
          right: 0,
          orient: this.direction,
          icon: 'rect',
          data: [],
          textStyle: {
            color: this.themeColor === 'default' ? '#000' : this.themeColor,
            fontSize: 16 * this.scale,
          },
          ...this.legendOption,
        },
        tooltip: {
          trigger: 'axis',
          axisPointer: {
            type: 'shadow',
          },
          textStyle: {
            fontSize: 16 * this.scale,
            fontWeight: 'bold',
          },
          formatter: (params) => {
            let tooltip = `<div>${params[0].name}</div>`;
            params.forEach((item) => {
              tooltip += `<div>
                ${item.marker}
                <span style="color: #666;">${item.seriesName}</span>
                <span style="float: right;margin-left: 20px;color: #666;">${item.value || item.value === 0 ? item.value : '-'}${this.unit}</span>
              </div>`;
            });
            return tooltip;
          },
          backgroundColor: 'rgba(255, 255, 255, 0.8)',
          borderWidth: 1,
          borderColor: '#E5E5E5',
          extraCssText: 'box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.08);',
          ...this.tooltip,
        },
        xAxis: {},
        yAxis: {},
        series: [],
      };
      let categoryAxis = {
        type: 'category',
        boundaryGap: true,
        inverse: this.direction === 'vertical',
        axisTick: {
          show: false,
        },
        axisLine: {
          show: this.showCategoryAxisLine,
          lineStyle: {
            color: this.themeColor === 'default' ? 'rgba(0, 0, 0, 0.45)' : this.themeColor,
          },
        },
        axisLabel: {
          interval: 0,
          margin: 14 * this.scale,
          fontSize: 16 * this.scale,
          color: this.themeColor === 'default' ? '#171F36' : this.themeColor,
          formatter: (value) => value.split('年').join('年\n'),
          ...this.categoryAxisLabel,
        },
        data: [],
      };
      let valueAxis = {
        type: 'value',
        name: this.unit,
        nameTextStyle: {
          fontSize: 16 * this.scale,
          color: this.themeColor === 'default' ? 'rgba(0, 0, 0, 0.45)' : this.themeColor,
        },
        axisTick: {
          show: false,
        },
        axisLine: {
          show: false,
        },
        axisLabel: {
          margin: 20 * this.scale,
          fontSize: 16 * this.scale,
          color: this.themeColor === 'default' ? 'rgba(0, 0, 0, 0.45)' : this.themeColor,
        },
        splitLine: {
          show: this.showSplitLine,
          lineStyle: {
            type: 'dashed',
            color: this.themeColor === 'default' ? 'rgba(0, 0, 0, 0.3)' : this.themeColor,
            opacity: 0.25,
          },
        },
      };
      if (this.direction === 'horizontal') {
        this.option.grid.top = this.showLegend ? 100 * this.scale : 60 * this.scale;
        this.option.legend.top = 30 * this.scale;
        this.option.xAxis = categoryAxis;
        this.option.yAxis = this.showValueAxis ? valueAxis : { show: false };
      } else {
        this.option.grid.right = '12.5%';
        this.option.yAxis = categoryAxis;
        this.option.xAxis = this.showValueAxis ? valueAxis : { show: false };
      }
      this.option.grid = { ...this.option.grid, ...this.grid };
      this.chart.on('click', (params) => {
        if (params.componentType === 'series') this.$emit('click', params);
      });
      this.chart.on('legendselectchanged', (params) => {
        if (this.legendClick(params) !== 'default') {
          this.chart.setOption({
            legend: { selected: { [params.name]: true } },
          });
        }
      });
    },
    async updateChart() {
      this.option.title.text = this.title;
      this.option.title.show = this.title.length > 0;
      if (this.showLegend) {
        let legend = [];
        this.valueKeys.forEach((valueKey) => { legend.push({ name: valueKey.name, icon: 'rect' }); });
        this.option.legend.data = legend;
      }
      this.option[this.direction === 'horizontal' ? 'yAxis' : 'xAxis'].max = this.maxValue;
      if (this.axisAdaptive) {
        let max;
        let min;
        this.data.forEach((item) => {
          this.valueKeys.forEach((valueKey) => {
            if (typeof (max) === 'undefined' || max < item[valueKey.key]) max = item[valueKey.key];
            if (typeof (min) === 'undefined' || min > item[valueKey.key]) min = item[valueKey.key];
          });
        });
        if (max > min) {
          let adapt = {};
          await getAlgorithmResult({ max, min }).then((res) => { adapt = res; });
          this.option[this.direction === 'horizontal' ? 'yAxis' : 'xAxis'] = {
            ...this.option[this.direction === 'horizontal' ? 'yAxis' : 'xAxis'],
            ...adapt,
          };
        }
      }
      let axis = [];
      let series = [];
      this.valueKeys.forEach((item, index) => {
        series.push({
          type: 'bar',
          barWidth: 24 * this.scale,
          label: {
            show: this.showLabel,
            position: this.direction === 'horizontal' ? 'top' : 'right',
            distance: 5 * this.scale,
            fontSize: 14 * this.scale,
            color: this.themeColor === 'default' ? '#000' : this.themeColor,
            formatter: this.label,
          },
          itemStyle: {
            color: this.colors[index] || this.colors[0],
          },
          barGap: '0%',
          showBackground: this.showBackground,
          data: [],
        });
      });
      this.data.forEach((item, dataIndex) => {
        axis.push(item[this.categoryAxisKey]);
        this.valueKeys.forEach((valueKey, index) => {
          series[index].name = valueKey.name;
          series[index].data.push({
            itemStyle: {
              color: this.colors[this.colorful ? dataIndex : index] || this.colors[0],
            },
            ...item,
            name: item[this.categoryAxisKey],
            value: item[valueKey.key],
            unit: this.unit,
          });
          series[index] = { ...series[index], ...this.seriesOption[valueKey.name] };
        });
      });
      this.option[this.direction === 'horizontal' ? 'xAxis' : 'yAxis'].data = axis;
      this.option.series = series;
      this.chart.clear();
      this.chart.setOption(this.option);
    },
  },
  beforeDestroy() {
    if (this.chart) {
      this.chart.dispose();
      this.chart = null;
    }
  },
};
</script>

<style lang="scss" scoped>
.no-data {
  font-size: 20px;
  display: flex;
  justify-content: center;
  align-items: center;
}
</style>
